//
//  Matrix.cpp
//  IsoCplus
//
//  Created by 周张林 on 15/9/15.
//
//

#include <cmath>
#include "Matrix.h"

USING_NS_CC;

//旋转
Matrix& Matrix::rotate(float angle)
{
    
    auto c = std::cos(angle);
    auto s = std::sin(angle);
    
    auto a1 = a;
    auto c1 = c;
    auto tx1 = tx;
    
    a = a1 * c - b * s;
    b = a1 * s + b * c;
    c = c1 * c - d * s;
    d = c1 * s+ d * c;
    tx = tx1 * c - ty * s;
    ty = tx1 * s + ty * c;
    
    return *this;
}

//缩放
Matrix& Matrix::scale(float x,float y)
{
    a = a*x;
    d = d * y;
    tx = tx* x;
    ty = ty * y;
    return *this;
}

//移动
Matrix& Matrix::translate(float txx,float tyy)
{
    tx += txx;
    ty += tyy;
    return *this;
}

//归一
Matrix& Matrix::identity()
{
    a = 1;
    d = 1;
    b = 0;
    c = 0;
    tx = 0;
    ty = 0;
    return *this;
}


//转换点
Vec2 Matrix::transformPoint(const Vec2 &pt)
{
    return Vec2( a * pt.x + c * pt.y + tx, d * pt.y + b * pt.x +ty);
}

//反转点
Vec2 Matrix::deltaTransformPoint(const Vec2 &pt)
{
    return Vec2( a * pt.x + c * pt.y ,d * pt.y + b * pt.x);
}

//创建一个box
Matrix& Matrix::createBox(float scaleX, float scaleY, float rotation, float txx, float tyy)
{
    auto u = std::cos(rotation);
    auto v = std::sin(rotation);
    a = u * scaleX;
    b = v * scaleY;
    c = -v * scaleX;
    d = u * scaleY;
    tx = txx;
    ty = tyy;
    return *this;
}

Matrix& Matrix::createGradientBox(float width,float height,float rotation,float tx,float ty)
{
    return this->createBox(
                          width / 1638.4,
                          height / 1638.4,
                          rotation,
                          tx + width / 2,
                          ty + height / 2
                          );
    return *this;
}

//反转矩阵
Matrix& Matrix::invert()
{
    auto aa = a;
    auto bb = b;
    auto cc = c;
    auto dd = d;
    auto txx = tx;
    auto tyy = ty;
    auto det = aa * dd - bb * cc;
    
    if (!det) {
        return identity();
    }
    
    det = 1 / det;
    a = dd * det;
    b = -bb * det;
    c = -cc * det;
    d = aa * det;
    tx = -(aa * txx + cc * tyy);
    ty = -(bb * txx + dd * tyy);
    return *this;
}

//叠加矩阵
Matrix& Matrix::concat(const Matrix &m)
{
    auto a1 = a;
    auto a2 = m.a;
    auto b1 = b;
    auto b2 = m.b;
    auto c1 = c;
    auto c2 = m.c;
    auto d1 = d;
    auto d2 = m.d;
    auto tx1 = tx;
    auto tx2 = m.tx;
    auto ty1 = ty;
    auto ty2 = m.ty;
    a = a1 * a2 + b1 * c2;
    b = a1 * b2 + b1 * d2;
    c = c1 * a2 + d1 * c2;
    d = d1 * d2 + c1 * b2;
    tx = (tx1 * a2 + tx2) + ty1 * c2;
    ty = (ty1 * d2 + ty2) + tx1 * b2;
    return *this;
}
